home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / Apple II / Essentials / rTutors / Detailed.Docs / Rez.105 < prev   
Encoding:
Text File  |  1993-06-15  |  11.2 KB  |  212 lines  |  [TEXT/pdos]

  1. Rez 105
  2. Copyright January 15, 1991 by Tim Swihart
  3. All Rights Reserved
  4.  
  5.  
  6. This time around, we'll focus on what's new in Part 3.5.  There never was a 
  7. public version of Part 3.4 (it got lost in a shuffle on my hard drive one day).  
  8. The custom cursor was tossed overboard (it was put in partially just to show 
  9. how to do it), several new icons have been added (for drawing the "levels"), 
  10. and I've added two custom resources.  The big goal of this release is to show 
  11. custom resources - how to create them in Rez, how to use them from C 
  12. (which makes it fairly easy to see how to do it from any language), and some 
  13. of the things custom resources make possible.  In order to show non-trivial 
  14. custom resources, I had to add the extra icons (you want it to be at least a 
  15. little snazzy, right?).
  16.  
  17.  
  18. One other Cleanup:
  19. In Part 3.3, I hard-coded the locations on the screen of the icons I was 
  20. drawing.  That means that anytime I wanted to add, delete, or reposition an 
  21. icon I had to recompile and relink my application.  Not a very pretty way to 
  22. maintain something that should be as flexible as a game screen (you want it 
  23. to be VERY flexible during development and sometimes afterward [Arkanoid 
  24. II's game screen is flexible, that's why you can make custom screens for it]).
  25.  
  26. In Part 3.5, the locations of all icons in the window are kept in the resource 
  27. fork (they're part of one of the two custom resources I mentioned not long 
  28. ago).  The drawMyContents() routine simply uses the information in the 
  29. custom resources to determine how many icons to draw and where to draw 
  30. them at.  Using the tricks we learned earlier (Rez's "-a" flag and/or the 
  31. "include" statement in a Rez file), we don't have to rebuild the entire 
  32. resource fork to make even major changes to the screen's layout.  We only 
  33. need to rebuild the individual custom resource that controls that icon's 
  34. positioning.  No linking is needed either (while the link times for rTutor so 
  35. far have been short, link times on large apps are seemingly infinite - no 
  36. matter which linker you use).
  37.  
  38.  
  39. How's It Work?
  40. It may sound like magic, but it's not.  It's a simple application of the 
  41. principle of data abstraction I discussed in earlier releases of this tutorial 
  42. series.  To explain how it works, I first need to explain what the custom 
  43. resources are and how they're used.  Then the "magic" becomes obvious.
  44.  
  45.  
  46. Will Custom Resource #1 Please Stand Up?
  47. In order to protect ourselves as much as possible from changes in our data 
  48. (after all, icon locations are just data, right?), we need to change the way we 
  49. draw.  Instead of hard-coding everything (including how many icons we'll 
  50. draw), why not simply use a counted list (meaning a list whose first element 
  51. is the count of the number of items in it).
  52.  
  53. This requires a custom resource I called it an rMySpotList (all resource 
  54. names start with a lower case "r" by convention) because it's a list of "spots" 
  55. on the screen where I want to draw.  Why didn't I call it an "rPointList" 
  56. (since a "point" is already defined as an x/y location on the screen)?  
  57. Originally I did!  But, it turned out that I wanted MORE information than just 
  58. the x/y location, so I created a new structure that contained the info I 
  59. needed and called it a "spot" ("rover" is over used in my opinion).  Since I 
  60. really wanted a list of "spots", I had to create the rMySpotList.
  61.  
  62.  
  63. Brief Side-Note:
  64. In the C source, you can find the definition for a "Spot" as well as for a 
  65. "SpotList", but in the Rez source the "Spot" itself wasn't need and was never 
  66. created.  That means we have two custom resources, but three custom data 
  67. structures in our C source.  In C, we need the actual spot in order to get to
  68. its components.  In Rez, we create the spots, but never access their components 
  69. (remember, the "spot" itself exists in C so we can access its components).  If 
  70. you're lost on this point, don't sweat it -> it's a minor one.  Work through
  71. the source files and it'll become more obvious.
  72.  
  73.  
  74. Back to Custom Resource #1:
  75. Rez has an easy way to produce counted lists (which made this type of 
  76. custom resource REAL easy to create).  See the Rez source and then the Rez 
  77. manual for details on how I created the counted list in Rez (hint:  read about 
  78. "$$Countof" in the Rez manual).
  79.  
  80. When it comes time to draw the icons, we simply load the rMySpotList 
  81. resource and loop through all the spots in the list.  How do we know how 
  82. many spots are in the list?  Simple, we grab the "count" off the top of the 
  83. structure and use it as the upper boundary on our loop!  That's data 
  84. abstraction at work -> if our list grows, the count is bumped (which is PART 
  85. of the list) and the routine still works.  In essence, we're making the list
  86. tell us how many elements it has, then grabbing each of those elements.
  87.  
  88. Since the location the icons are drawn at is part of each "spot", we can use 
  89. larger or smaller icons and the ONLY change needed would be to tweak the 
  90. list so the x/y locations embedded within it reflect the bigger or smaller 
  91. icons.  No change would be required in the application itself!
  92.  
  93.  
  94. So Why Do We Need The Other One?
  95. In Part 3.3, we simply put one icon on the screen.  A "LoadRunner" style 
  96. game needs several different icons (one for the "floor", one for the "ladder", 
  97. etc).  How do we know in advance how many icons are allow per level?  Do 
  98. we just force a limit into our C source?  NO!!!
  99.  
  100. Let's reflect on the lessons we just learned from the first custom resource.  
  101. What if we had something in the resource fork that told us how many icons 
  102. were used on a particular level?  Hmmm....
  103.  
  104. Wait a sec.  What if we want one level to look like a land scene (floors, 
  105. ladders, etc) and another level to look radically different?  If all we know
  106. is how many icons are available per level, then we'd have to always use the 
  107. same icons.  Why not take this one step further?
  108.  
  109. What if we created a custom resource that not only told us how many icons 
  110. were on a given level, but what their resource ID's were?  That would let us 
  111. draw as many different icons on each level as we could ever want!
  112.  
  113. And thus, custom resource #2 was born.  Called an "rWhichIconsUsed" 
  114. resource, this one is also a counted list.  The count field tells us how many 
  115. icons are used on this level and the rest of the list is the ID of each icon
  116. used for that level.  This one is probably easier to grasp than the
  117. rMySpotList since its structure is much simpler.
  118.  
  119. With this second structure in place, we can now modify our window content 
  120. drawing routine to contain a nested loop.  The outer loop runs through each 
  121. icon that's going to be on the screen and the inner loop draw that icon at
  122. all of its locations.  The end result is that we draw all of one icon, then
  123. all of the next, then the next, and so on.  The whole thing is reasonably
  124. quick and if you create the list right you can force some visual effects into
  125. the drawing (making it appear that the screen is drawn in a right to left
  126. sweeping motion or top to bottom or...).
  127.  
  128.  
  129. Important Note:
  130. Did you catch that we're letting Rez do our counting for us?  We can delete a 
  131. random number of elements from either of these custom resources, 
  132. recompile, and it'll work.  Why?  Because the "count" field is filled in by
  133. Rez at compile time and accurately reflects the number of elements in the list.  
  134. This means we can also add elements freely without having to recount them 
  135. (Rez has to recount them).  Let your tools do the mundane stuff (like 
  136. counting the number of items in a list) whenever possible.
  137.  
  138.  
  139. Can I Make These Resources With Other Tools?
  140. Sure, you could write a custom editor for GeneSys (Great app - do you have 
  141. it yet?  If not, you should.) but I have yet to be able to visualize a good 
  142. interface for it.  It would be fairly simple to just create a stand-alone 
  143. desktop app that lets you pick a given icon, slam it around on the screen 
  144. (force it to "snap" to the "grid" locations that correspond to that size icon), 
  145. then create either the Rez source or the actual resource.  Your custom app 
  146. would have to do the counting since that value is VERY important.  
  147. Personally, I think the easiest way to create an editor like this is with 
  148. HyperCard IIGS, but that's a subject for another day.  :-)
  149.  
  150.  
  151. Wait a Second...
  152. It should have occurred to you by know (no points off it it didn't though) 
  153. that we're cramming a bunch of stuff into resource without giving much 
  154. consideration for how we're going to tell one level's list from another's.
  155. For the SpotLists, we have a real problem!  Each icon has to have a separate 
  156. SpotList for EACH level.   Hmmm, what if we looked at the resource ID as a 
  157. hex number, then split the hex digits into pieces?  One piece could be used to 
  158. denote which icon it's for and another piece could be used to denote which 
  159. level that list is for.  There's a detailed comment in the Rez source for Part 
  160. 3.5 that shows how we do this.  Assembly programmers will catch on right 
  161. away (it's just like packing bits to save space).
  162.  
  163. We don't have to pull any fancy stunts for the resource ID's of the 
  164. rWhichIconsUsed resources.  There's only one of them per level, so just make 
  165. their ID's equal the level the represent.  i.e.:  the rWhichIconsUsed list for 
  166. level 1 would have a resource ID of 1, level 2's would have an ID of 2, etc.
  167.  
  168.  
  169. One More Thing:
  170. Speaking of data abstraction and how it can helps us minimize waste caused 
  171. by change.  The x/y locations used in Part 3.3 were hard coded and were 
  172. based on the height and width of the icons.  If we switched to different sized 
  173. icons, every one of the x/y's had to be tweaked.  What if we defined a 
  174. constant that reflected the height (in pixels) of the icons we're using and 
  175. another one that reflected the width (in pixels)?  If we changed the icon's 
  176. size, we'd only have to change the two constants and recompile!  Much less 
  177. work, wouldn't you agree?
  178.  
  179. Look in the Rez source file at the different SpotLists.  One of them is hard-
  180. coded and the others use the constants.  Compile time for the hard-code one 
  181. is a little faster (less math for the compiler to do), but changes are VERY 
  182. hard.  When developing software (especially stuff you expect to use over and 
  183. over) be sure to keep an eye out for ways to do things that reduce 
  184. "maintenance time" (the time you spend making changes, fixing bugs, etc).  
  185. You may take a little hit on compile time, but you often will save MUCH more 
  186. time in the long run.  Don't go overboard - learn when the trade off between 
  187. raw compile speed and ease of maintenance should be made.  Trial and error 
  188. (with forethought and some 20-20 hindsight) should be a good teacher.
  189.  
  190.  
  191. Next Time Around:
  192. We'll add the code to make the "player" icon move.  Start thinking about the 
  193. best way to do this (and the easiest).  We don't want to have to redraw the 
  194. entire screen on each move, just the area affected.  Do we need more custom 
  195. data structures?  If so, what would they look like?  (there are undoubtedly 
  196. several correct answers here).
  197.  
  198.  
  199. On Your Own:
  200. The layout for level 1 that I've provided is pretty weak (I just slammed a 
  201. bunch of numbers down in a hurry).  Spend a little time laying out a real 
  202. screen.  Send it to me (email is fine) and I'll put the best of them into the 
  203. next release.  That will force you to go through what a Spot really is, how to 
  204. create a spot list, etc.  It'll also save me from having to do a better level.  
  205. <grin>
  206.  
  207.  
  208.  
  209.  
  210. Enjoy,
  211. Tim S.
  212.